Emberveil source

game/2006Scape Client/src/main/java/ChatCrowns.java

/** Server-assigned chat ranks. Crown tags never come from the message body. */
public final class ChatCrowns {
    private ChatCrowns() {}

    public static String prefix(int rights) {
        return rights >= 1 && rights <= 3 ? "@cr" + rights + "@" : "";
    }

    public static int rank(String name) {
        if(name == null) return 0;
        for(int rank=1;rank<=3;rank++) if(name.startsWith(prefix(rank))) return rank;
        return 0;
    }

    public static String strip(String name) {
        return rank(name) == 0 ? name : name.substring(5);
    }

    /** Preserve the original old-school crown silhouette and transparent pixels. */
    public static Background owner(StreamLoader archive) {
        Background crown = new Background(archive,"mod_icons",1);
        for(int i=1;i<crown.anIntArray1451.length;i++) {
            int rgb=crown.anIntArray1451[i];
            int light=Math.max(rgb>>16&255,Math.max(rgb>>8&255,rgb&255));
            // Ember-red body with warm flame highlights; preserve the classic mask.
            crown.anIntArray1451[i]=(85+light*170/255)<<16 | light*35/255<<8 | light*45/255;
        }
        crown.ownerFlame = true;
        return crown;
    }
    public static Background coOwner(StreamLoader archive) {
        Background crown = owner(archive);
        for (int i=1;i<crown.anIntArray1451.length;i++) crown.anIntArray1451[i]=green(crown.anIntArray1451[i]);
        crown.coOwnerFlame=true;
        return crown;
    }
    /** Identity comes from the authenticated chat sender, never message text. */
    public static int icon(int rights,String name) {
        return rights==3 && "darren".equalsIgnoreCase(strip(name)) ? 3 : Math.max(0,Math.min(2,rights-1));
    }
    private static int green(int rgb) { return (rgb&0xff) | (rgb>>16&255)<<8 | (rgb>>8&255)<<16; }
    private static void flame(Background crown,int x,int y,int rgb,int alpha) {
        blend(x,y,crown.coOwnerFlame ? green(rgb) : rgb,alpha);
    }
    /** Small, bounded flame tongues and a blended red halo, without covering names. */
    public static void drawOwner(Background crown, int x, int y, long time) {
        int frame = (int)((time / 120L) % 6);
        int left = x + crown.anInt1454, top = y + crown.anInt1455;
        int w = crown.anInt1452, h = crown.anInt1453;
        // Draw the soft halo first. Transparent source pixels stay transparent.
        for (int yy=0; yy<h; yy++) for (int xx=0; xx<w; xx++) {
            if (crown.aByteArray1450[xx+yy*w] == 0) continue;
            flame(crown,left+xx-1,top+yy,0xff1028,55);
            flame(crown,left+xx+1,top+yy,0xff1028,55);
            flame(crown,left+xx,top+yy-1,0xff1028,65);
            flame(crown,left+xx,top+yy+1,0xff1028,45);
        }
        // Three red fire tongues rise from the crown's points; the tips flicker.
        for (int tip=0; tip<3; tip++) {
            int xx = tip == 0 ? 1 : tip == 1 ? w/2 : w-2;
            int rise = 2 + (frame+tip*2)%3;
            for (int yy=0; yy<rise; yy++) {
                int sway = yy == rise-1 ? ((frame+tip)%3)-1 : 0;
                flame(crown,left+xx+sway,top-yy,yy == 0 ? 0xff7386 : 0xff263e,220-yy*25);
                flame(crown,left+xx+sway-1,top-yy,0xff1234,55);
                flame(crown,left+xx+sway+1,top-yy,0xff1234,55);
            }
        }
        // Keep the readable classic crown body on top of the glow.
        for (int yy=0; yy<h; yy++) for (int xx=0; xx<w; xx++) {
            int index = crown.aByteArray1450[xx+yy*w]&255;
            if (index != 0) blend(left+xx,top+yy,crown.anIntArray1451[index],256);
        }
    }

    private static void blend(int x, int y, int rgb, int alpha) {
        if (x<DrawingArea.topX || x>=DrawingArea.bottomX || y<DrawingArea.topY || y>=DrawingArea.bottomY) return;
        int at=x+y*DrawingArea.width, old=DrawingArea.pixels[at], inverse=256-alpha;
        DrawingArea.pixels[at]=(((rgb&0xff00ff)*alpha+(old&0xff00ff)*inverse)&0xff00ff00
            | ((rgb&0x00ff00)*alpha+(old&0x00ff00)*inverse)&0x00ff0000)>>>8;
    }

    public static boolean hasOwner(String[] names, String[] messages) {
        for (int i=0; i<names.length && i<messages.length; i++)
            if (messages[i]!=null && rank(names[i])==3) return true;
        return false;
    }
}